package com.xfzp.android.ms;

import com.xfzp.d3.Axis;
import com.xfzp.d3.Color;
import com.xfzp.d3.Coord;
import com.xfzp.d3.Cube;
import com.xfzp.d3.Ray;
import com.xfzp.d3.Shape;
import com.xfzp.d3.Vertex;
import com.xfzp.d3.World;

/**
 * 魔方
 * 
 * @author AndroidApe
 * @version 2011-11-11
 */
public class Kube2 extends World {
	public static final float cubeWidth = 0.63f;
	public static final float spaceWidth = 0.055f;

	private float[] scale;// 每个轴上的6个刻度值
	private Vertex[] vs;// 边界上的8个顶点
	private short[] index;// 边界上8个顶点组成的三角形顺序

	private int[] cubeOrder;
	private Layer[] layers;// 绕每个轴可旋转的3个层，共9个层

	public Kube2(int[] cubeOrder) {
		initCubeOrder(cubeOrder);
		initBorder(cubeWidth, spaceWidth);
		initCube();
		initLayer();
		updateLayerCube();
	}

	/**
	 * 返回层顺序
	 * 
	 * @return
	 */
	public int[] getCubeOrder() {
		return cubeOrder;
	}

	/**
	 * 选择转动的层
	 * 
	 * @param ray
	 * @param dir
	 * @return
	 */
	public AbleLayer rayPickup(Ray ray, Coord dir) {
		int face = -1;
		Float t = null;
		Float tmp_t;
		for (int i = 0; i < 36;) {
			tmp_t = ray.intersectTriangle(vs[index[i++]], vs[index[i++]],
					vs[index[i++]]);
			if (tmp_t != null) {
				if (t == null || tmp_t < t) {
					t = tmp_t;
					face = i;
				}
			}
		}
		if (t != null) {
			face = (face - 3) / 6;
			Coord interPoint = ray.count(t);
			float abs_x = Math.abs(dir.x());
			float abs_y = Math.abs(dir.y());
			float abs_z = Math.abs(dir.z());
			int sl = -1;
			if (face == 0 || face == 3) {
				if (abs_x > abs_y) {
					sl = selectLayer(interPoint.y(), 3);
				} else {
					sl = selectLayer(interPoint.x(), 0);
				}
			} else if (face == 1 || face == 4) {
				if (abs_z > abs_x) {
					sl = selectLayer(interPoint.x(), 0);
				} else {
					sl = selectLayer(interPoint.z(), 6);
				}
			} else if (face == 2 || face == 5) {
				if (abs_y > abs_z) {
					sl = selectLayer(interPoint.z(), 6);
				} else {
					sl = selectLayer(interPoint.y(), 3);
				}
			}
			if (sl > -1) {
				return new AbleLayer(sl, face > 2);
			}
		}
		return null;
	}

	/**
	 * 旋转指定的活动层。如果没有旋转返回-1；否则累加每次旋转的角度，返回累加的和除以90度的值，并将余数继续累加
	 */
	public int roundAbleLayer(AbleLayer ableLayer) {
		float a = ableLayer.nextRotateAngle();
		if (a != 0) {
			Layer layer = layers[ableLayer.getLayerId()];
			layer.rotate(a);
			int rc = ableLayer.resumeHasRotateAngle();
			boolean cw = true;
			if (rc < 0) {
				rc = -rc;
				cw = false;
			}
			if (rc > 0) {
				for (int i = 0; i < rc; i++) {
					updateOrder(layer, cw);
				}
				updateLayerCube();
			}
			return rc;
		}
		return -1;
	}

	/**
	 * 返回层的序号
	 * 
	 * @param s
	 * @param base
	 * @return
	 */
	private int selectLayer(float s, int base) {
		if (s <= scale[1] && s >= scale[0]) {
			return base;
		} else if (s <= scale[3] && s >= scale[2]) {
			return base + 1;
		} else if (s <= scale[5] && s >= scale[4]) {
			return base + 2;
		}
		return -1;
	}

	/**
	 * 初始化立方体顺序
	 */
	private void initCubeOrder(int[] cubeOrder) {
		if (cubeOrder != null && cubeOrder.length == 26) {
			this.cubeOrder = cubeOrder;
		} else {
			this.cubeOrder = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
					12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
		}
	}

	/**
	 * 初始化边界值及顶点
	 * 
	 * @param cw
	 * @param sw
	 */
	private void initBorder(float cw, float sw) {
		scale = new float[6];
		scale[3] = cw / 2;
		scale[2] = -scale[3];
		scale[1] = scale[2] - sw;
		scale[0] = scale[1] - cw;
		scale[4] = scale[3] + sw;
		scale[5] = scale[4] + cw;
		vs = new Vertex[] { new Vertex(scale[0], scale[0], scale[0]),
				new Vertex(scale[0], scale[5], scale[0]),
				new Vertex(scale[5], scale[5], scale[0]),
				new Vertex(scale[5], scale[0], scale[0]),
				new Vertex(scale[0], scale[0], scale[5]),
				new Vertex(scale[0], scale[5], scale[5]),
				new Vertex(scale[5], scale[5], scale[5]),
				new Vertex(scale[5], scale[0], scale[5]) };
		index = new short[] { 4, 7, 5, 7, 6, 5, 1, 5, 2, 5, 6, 2, 2, 6, 3, 6,
				7, 3, 1, 2, 0, 2, 3, 0, 0, 3, 4, 3, 7, 4, 0, 4, 1, 4, 5, 1 };
	}

	/**
	 * 初始化小立方体。小立方体在World中的索引顺序按从后到前，从下到上，从左到右
	 */
	private void initCube() {
		int t1, t2, t3;
		for (int k = 0; k < 6; k++) {
			t3 = k++;
			for (int j = 0; j < 6; j++) {
				t2 = j++;
				for (int i = 0; i < 6; i++) {
					t1 = i++;
					if (t3 == 2 && t2 == 2 && t1 == 2) {
						continue;
					}
					add(new Cube(new Vertex(scale[t1], scale[t2], scale[t3]),
							new Vertex(scale[i], scale[j], scale[k])));
				}
			}
		}
		Shape c;
		int i2;
		for (int i : cubeOrder) {
			c = get(i);
			i2 = i % 3;
			c.set(Color.BALCK, 0, 1, 2, 3, 4, 5);
			if (i < 13) {
				if (i < 9) {
					c.set(Color.ORANGE, 0);
				}
				if (i2 == 0) {
					c.set(Color.BLUE, 1);
				} else if (i2 == 2) {
					c.set(Color.GREEN, 3);
				}
				if (i < 3 || (i > 8 && i < 12)) {
					c.set(Color.YELLOW, 4);
				} else if (i > 5 && i < 9) {
					c.set(Color.WHITE, 2);
				}
			} else {
				if (i > 16) {
					c.set(Color.RED, 5);
				}
				if (i2 == 2) {
					c.set(Color.BLUE, 1);
				} else if (i2 == 1) {
					c.set(Color.GREEN, 3);
				}
				if (i > 16 && i < 20) {
					c.set(Color.YELLOW, 4);
				} else if ((i > 13 && i < 17) || i > 22) {
					c.set(Color.WHITE, 2);
				}
			}
		}
	}

	/**
	 * 初始化层
	 */
	private void initLayer() {
		layers = new Layer[] {
				new Layer(Axis.X, new int[] { 0, 9, 17, 20, 23, 14, 6, 3, 12 }),
				new Layer(Axis.X, new int[] { 1, 10, 18, 21, 24, 15, 7, 4 }),
				new Layer(Axis.X, new int[] { 2, 11, 19, 22, 25, 16, 8, 5, 13 }),
				new Layer(Axis.Y, new int[] { 0, 1, 2, 11, 19, 18, 17, 9, 10 }),
				new Layer(Axis.Y, new int[] { 3, 4, 5, 13, 22, 21, 20, 12 }),
				new Layer(Axis.Y, new int[] { 6, 7, 8, 16, 25, 24, 23, 14, 15 }),
				new Layer(Axis.Z, new int[] { 0, 3, 6, 7, 8, 5, 2, 1, 4 }),
				new Layer(Axis.Z, new int[] { 9, 12, 14, 15, 16, 13, 11, 10 }),
				new Layer(Axis.Z, new int[] { 17, 20, 23, 24, 25, 22, 19, 18,
						21 }) };
	}

	/**
	 * 更新层的顺序
	 * 
	 * @param layer
	 * @param cw
	 */
	private void updateOrder(Layer layer, boolean cw) {
		int[] cubeIndex = layer.getCubeIndex();
		int len = 8;
		if (cw) {
			int i = 2;
			int t0 = cubeOrder[cubeIndex[0]];
			int t1 = cubeOrder[cubeIndex[1]];
			for (; i < len; i++) {
				cubeOrder[cubeIndex[i - 2]] = cubeOrder[cubeIndex[i]];
			}
			cubeOrder[cubeIndex[i - 2]] = t0;
			cubeOrder[cubeIndex[i - 1]] = t1;
		} else {
			int i = len - 1;
			int t0 = cubeOrder[cubeIndex[i - 1]];
			int t1 = cubeOrder[cubeIndex[i]];
			for (; i > 1; i--) {
				cubeOrder[cubeIndex[i]] = cubeOrder[cubeIndex[i - 2]];
			}
			cubeOrder[cubeIndex[0]] = t0;
			cubeOrder[cubeIndex[1]] = t1;
		}
	}

	/**
	 * 更新层的立方体
	 */
	private void updateLayerCube() {
		int[] cubeIndex;
		for (Layer l : layers) {
			cubeIndex = l.getCubeIndex();
			for (int j = 0, len = cubeIndex.length; j < len; j++) {
				l.setCube(j, (Cube) get(cubeOrder[cubeIndex[j]]));
			}
		}
	}
}
